package com.yikes.srb.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yikes.srb.common.result.PageResult;
import com.yikes.srb.common.utils.object.BeanUtils;
import com.yikes.srb.constant.hfb.FormHelper;
import com.yikes.srb.constant.hfb.HfbConst;
import com.yikes.srb.constant.hfb.RequestHelper;
import com.yikes.srb.leadingModle.form.lendReturn.LendReturnAddForm;
import com.yikes.srb.leadingModle.form.lendReturn.LendReturnEditForm;
import com.yikes.srb.leadingModle.form.lendReturn.LendReturnQuery;
import com.yikes.srb.leadingModle.vo.LendReturnVO;
import com.yikes.srb.mapper.*;
import com.yikes.srb.pojo.bo.TransFlowBO;
import com.yikes.srb.pojo.entity.Lend;
import com.yikes.srb.pojo.entity.LendItem;
import com.yikes.srb.pojo.entity.LendItemReturn;
import com.yikes.srb.pojo.entity.LendReturn;
import com.yikes.srb.pojo.enums.LendStatusEnum;
import com.yikes.srb.pojo.enums.ServiceWorkCodeEnum;
import com.yikes.srb.pojo.enums.TransTypeEnum;
import com.yikes.srb.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yikes.srb.util.LendNoUtils;
import com.yikes.srb.web.utils.As;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 还款记录表 服务实现类
 * </p>
 *
 * @author guanrong.yin
 * @since 2024-12-03
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class LendReturnServiceImpl extends ServiceImpl<LendReturnMapper, LendReturn> implements LendReturnService {

    private final UserAccountService userAccountService;

    private final LendMapper lendMapper;

    private final UserBindService userBindService;

    private final LendItemReturnService lendItemReturnService;

    private final TransFlowService transFlowService;

    private final UserAccountMapper userAccountMapper;

    private final LendItemReturnMapper lendItemReturnMapper;

    private final LendItemMapper lendItemMapper;

    private final DictService dictService;

    @Override
    public PageResult<LendReturnVO> listPage(LendReturnQuery query) {

        Page<LendReturn> page = lambdaQuery()
                .eq(ObjectUtil.isNotNull(query.getLendId()), LendReturn::getLendId, query.getLendId())
                .like(StrUtil.isNotBlank(query.getReturnNo()), LendReturn::getReturnNo, query.getReturnNo())
                .eq(ObjectUtil.isNotNull(query.getReturnMethod()), LendReturn::getReturnMethod, query.getReturnMethod())
                .eq(ObjectUtil.isNotNull(query.getIsOverdue()), LendReturn::getIsOverdue, query.getIsOverdue())
                .eq(ObjectUtil.isNotNull(query.getStatus()), LendReturn::getStatus, query.getStatus())
                .page(Page.of(query.getPageNum(), query.getPageSize()));

        List<LendReturnVO> bean = BeanUtils.toBean(page.getRecords(), LendReturnVO.class);
        return PageResult.build(page.getTotal(), page.getPages(), bean);

    }

    @Override
    public LendReturnVO infoId(Long id) {

        LendReturn lendReturn = getById(id);
        LendReturnVO bean = BeanUtils.toBean(lendReturn, LendReturnVO.class);
        return bean;

    }

    @Override
    public void create(LendReturnAddForm form) {

        LendReturn bean = BeanUtils.toBean(form, LendReturn.class);
        save(bean);
    }

    @Override
    public void edit(LendReturnEditForm form) {

        LendReturn bean = BeanUtils.toBean(form, LendReturn.class);
        updateById(bean);

    }

    @Override
    public void del(Long id) {
        baseMapper.deleteById(id);
    }

    @Override
    public List<LendReturnVO> selectByLendId(Long lendId) {

        List<LendReturn> list = lambdaQuery().eq(LendReturn::getLendId, lendId).list();
        if (CollUtil.isEmpty(list)) {
            return CollUtil.empty(List.class);
        }

        List<LendReturnVO> lendReturnVOS = Lists.newArrayList();
        for (LendReturn lendReturn : list) {
            LendReturnVO bean = BeanUtils.toBean(lendReturn, LendReturnVO.class);

            String returnMethod = dictService.getNameByParentDictCodeAndValue("returnMethod", Integer.valueOf(lendReturn.getReturnMethod()));
            bean.setReturnMethod(returnMethod);
            if (lendReturn.getStatus() == 1) {
                bean.setStatus("已归还");
            } else {
                bean.setStatus("未归还");
            }

            lendReturnVOS.add(bean);
        }

        return lendReturnVOS;
    }

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public String commitReturn(Long lendReturnId, Long userId) {

        //获取还款记录
        LendReturn lendReturn = baseMapper.selectById(lendReturnId);

        //判断账号余额是否充足
        BigDecimal amount = userAccountService.getAccount(userId);
        As.isTure(amount.doubleValue() >= lendReturn.getTotal().doubleValue(),
                ServiceWorkCodeEnum.NOT_SUFFICIENT_FUNDS_ERROR);

        //获取借款人code
        String bindCode = userBindService.getBindCodeByUserId(userId);
        //获取lend
        Long lendId = lendReturn.getLendId();
        Lend lend = lendMapper.selectById(lendId);

        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("agentId", HfbConst.AGENT_ID);
        //商户商品名称
        paramMap.put("agentGoodsName", lend.getTitle());
        //批次号
        paramMap.put("agentBatchNo", lendReturn.getReturnNo());
        //还款人绑定协议号
        paramMap.put("fromBindCode", bindCode);
        //还款总额
        paramMap.put("totalAmt", lendReturn.getTotal());
        paramMap.put("note", "");
        //还款明细
        List<Map<String, Object>> lendItemReturnDetailList = lendItemReturnService.addReturnDetail(lendReturnId);
        paramMap.put("data", JSONObject.toJSONString(lendItemReturnDetailList));
        paramMap.put("voteFeeAmt", new BigDecimal(0));
        paramMap.put("notifyUrl", HfbConst.BORROW_RETURN_NOTIFY_URL);
        paramMap.put("returnUrl", HfbConst.BORROW_RETURN_RETURN_URL);
        paramMap.put("timestamp", RequestHelper.getTimestamp());
        String sign = RequestHelper.getSign(paramMap);
        paramMap.put("sign", sign);

        //构建自动提交表单
        return FormHelper.buildForm(HfbConst.BORROW_RETURN_URL, paramMap);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void notify(Map<String, Object> paramMap) {

        log.info("还款成功");

        // 还款编号
        String agentBatchNo = (String) paramMap.get("agentBatchNo");
        boolean result = transFlowService.isSaveTransFlow(agentBatchNo);
        if (result) {
            log.warn("幂等性返回");
            return;
        }

        // 获取还款数据
        String voteFeeAmt = (String) paramMap.get("voteFeeAmt");
        LendReturn lendReturn = lambdaQuery().eq(LendReturn::getReturnNo, agentBatchNo).one();

        // 更新还款状态
        lendReturn.setStatus(1);
        lendReturn.setFee(new BigDecimal(voteFeeAmt));
        lendReturn.setRealReturnTime(LocalDateTime.now());
        baseMapper.updateById(lendReturn);

        // 更新标的信息
        Lend lend = lendMapper.selectById(lendReturn.getLendId());
        //最后一次还款更新标的状态
        if (lendReturn.getIsLast() == 1) {
            lend.setStatus(LendStatusEnum.PAY_OK.getStatus());
            lendMapper.updateById(lend);
        }

        // 借款账号转出金额
        // 还款金额
        BigDecimal totalAmt = new BigDecimal((String) paramMap.get("totalAmt"));
        String bindCode = userBindService.getBindCodeByUserId(lend.getUserId());
        userAccountMapper.updateAccount(bindCode, totalAmt.negate(), new BigDecimal(0));

        // 借款人交易流水
        TransFlowBO transFlowBO = new TransFlowBO(
                agentBatchNo,
                bindCode,
                totalAmt,
                TransTypeEnum.RETURN_DOWN,
                "借款人还款扣减，项目编号：" + lend.getLendNo() + "，项目名称：" + lend.getTitle());
        transFlowService.saveTransFlow(transFlowBO);

        // 获取回款明细
        List<LendItemReturn> lendItemReturnList = lendItemReturnService.selectLendItemReturnList(lendReturn.getId());
        lendItemReturnList.forEach(item -> {
            //更新回款状态
            item.setStatus(1);
            item.setRealReturnTime(LocalDateTime.now());
            lendItemReturnMapper.updateById(item);

            //更新出借信息
            LendItem lendItem = lendItemMapper.selectById(item.getLendItemId());
            lendItem.setRealAmount(item.getInterest());
            lendItemMapper.updateById(lendItem);

            //投资账号转入金额
            String investBindCode = userBindService.getBindCodeByUserId(item.getInvestUserId());
            userAccountMapper.updateAccount(investBindCode, item.getTotal(), new BigDecimal(0));

            //投资账号交易流水
            TransFlowBO investTransFlowBO = new TransFlowBO(
                    LendNoUtils.getReturnItemNo(),
                    investBindCode,
                    item.getTotal(),
                    TransTypeEnum.INVEST_BACK,
                    "还款到账，项目编号：" + lend.getLendNo() + "，项目名称：" + lend.getTitle());
            transFlowService.saveTransFlow(investTransFlowBO);
        });

    }
}
